package com.mytomcat.catalina.net;

/**
 * 同步循环队列
 *
 * @author supu
 * @date 2019-04-23 14:06
 **/
public class SynchronizedQueue<T> {
    /**
     * 默认长度
     */
    private static final int DEFAULT_SIZE = 128;
    /**
     * 插入位置索引
     */
    private int insertIndex;
    /**
     * 删除位置索引
     */
    private int removeIndex;
    /**
     * 队列长度
     */
    private int size;

    private Object[] queue;

    public SynchronizedQueue() {
        this(DEFAULT_SIZE);
    }

    public SynchronizedQueue(int size) {
        this.size = size;
        queue = new Object[size];
    }

    /**
     * add数据
     *
     * @param object 对象
     * @return
     */
    public synchronized boolean offer(Object object) {
        queue[insertIndex++] = object;

        // 队列插满数据，从头位置开始插入（循环插入）
        if (insertIndex == size) {
            insertIndex = 0;
        }

        // 当插入位置和删除位置索引碰撞了，说明队列数据满了，需要扩容
        if (insertIndex == removeIndex) {
            // 扩容
            expand();
        }

        return true;
    }

    /**
     * 删除对象
     *
     * @return
     */
    public synchronized T poll() {
        if (insertIndex == removeIndex) {
            return null;
        }
        T object = (T) queue[removeIndex];
        queue[removeIndex] = null;
        removeIndex++;

        // 移除到size索引数据后，从头开始
        if (removeIndex == size) {
            removeIndex = 0;
        }

        return object;
    }

    /**
     * 扩容
     */
    private void expand() {
        int newSize = size * 2;
        Object[] newQueue = new Object[newSize];

        System.arraycopy(queue, insertIndex, newQueue, 0, size - insertIndex);
        System.arraycopy(queue, 0, newQueue, size - insertIndex, insertIndex);

        insertIndex = size;
        removeIndex = 0;
        queue = newQueue;
        size = newSize;
    }

    /**
     * 获取队列中数据长度
     *
     * @return
     */
    public synchronized int size() {
        int result = insertIndex - removeIndex;
        if (result < 0) {
            result += size;
        }
        return result;
    }

    /**
     * 清空队列
     */
    public synchronized void clear(){
        for(int i =0; i < size(); i++){
            queue[i] = null;
        }
        insertIndex = 0;
        removeIndex = 0;
    }
}
